package com.cloud.demo.login.config;

import com.alibaba.fastjson.JSON;
import com.cloud.demo.common.result.BaseResult;
import com.cloud.demo.common.result.ErrorCodeEnum;
import com.cloud.demo.common.result.ErrorMessage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 统一日志管理
 *
 * @author szj
 * @date 2020/10/9
 */
@Aspect
@Component
public class WebLogAspect {
    private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Value(value = "${printLog}")
    private boolean printLog;

    @Pointcut("execution(public * com.cloud.demo.*.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public BaseResult before() {
        logger.info("before");
        return new BaseResult(null);
    }

    @Around("webLog()")
    public BaseResult doAround(ProceedingJoinPoint pjp) {
        long startTime = System.currentTimeMillis();
        BaseResult result;
        // 获取请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String method = request.getRequestURL().toString();
        // debug输出
        if (printLog) {
            logger.info(getRequestInfo(request, pjp));
        }
        try {
            Object obj = pjp.proceed();
            result = (BaseResult) obj;
        } catch (Throwable throwable) {
            logger.error(ErrorMessage.INTERNAL_ERROR + "\n接口:" + request.getRequestURL()
                    + "\n参数:" + Arrays.toString(pjp.getArgs()), throwable);
            result = new BaseResult(ErrorCodeEnum.INTERNAL_ERROR, throwable.getMessage(), null);
        }
        // debug输出
        if (printLog) {
            logger.info(getResultInfo(method, JSON.toJSONString(result), System.currentTimeMillis() - startTime));
        }
        return result;
    }

    private String getRequestInfo(HttpServletRequest request, ProceedingJoinPoint pjp) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("\nUrl:")
                .append(request.getRequestURL())
                .append("\nMethod:")
                .append(request.getMethod())
                .append("\nIP:")
                .append(request.getRemoteAddr())
                .append("\nArgs:")
                .append(Arrays.toString(pjp.getArgs()));
        if (request.getHeader("userId") != null) {
            stringBuilder.append("\nUserId:").append(request.getHeader("userId"));
        }
        return stringBuilder.toString();
    }

    private String getResultInfo(String method, String result, long timeCost) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(method)
                .append("\n返回结果:")
                .append(result)
                .append("\n执行耗时(ms):")
                .append(timeCost);
        return stringBuilder.toString();
    }
}
